//
//  DrawInContextView.m
//  CoreAnimation
//
//  Created by 张国文 on 16/10/13.
//  Copyright © 2016年 hangzhouyijiyin. All rights reserved.
//

#import "DrawInContextView.h"

@interface DrawInContextView ()

@property (nonatomic, strong) NSString *showString;

@end

@implementation DrawInContextView

// ⚠️重要结论：UIView的内部是执行drawRect的和- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx，但是一旦我们显示的调用self.layer display的话，drawRect是不会被执行的（除非我们重写这个方法，并且重写drawLayer inContext，drawincontext会反过来影响drawRect，因此drawRect会重新执行一次(即：两次，视图第一次加载的时候一次，display一次)），即如果调用display的话，如果想要调用drawRect的话，必须重写- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx和drawRect


/*⚠️⚠️⚠️⚠️可以看出当一个view被addsubview到其他view上时
 1.先隐式地把此view的layer的CALayerDelegate设置成此view
 2.调用此view的self.layer的drawInContext方法
 3.由于drawLayer方法的注释 If defined, called by the default implementation of -drawInContext:
 说明了drawInContext里if([self.delegate responseToSelector:@selector(drawLayer:inContext:)])时就执行drawLayer:inContext:方法，这里我们因为实现了drawLayer:inContext:所以会执行
 4.[super drawLayer:layer inContext:ctx]会让系统自动调用此view的drawRect:方法
 至此self.layer画出来了
 5.在self.layer上再加一个子layer，当调用[layer setNeedsDisplay];时会自动调用此layer的drawInContext方法。drawInContext方法不能手动调用，只能通过这个方法让系统自动调用
 6.如果drawRect不重写，就不会调用其layer的drawInContext方法，也就不会调用重写drawLayer:inContext方法---要重写就一起重写
 7.系统默认是会调用drawInContext和drawRect方法的,在默认drawLayer:inContext的方法中，系是会重写[super drawLayer:layer inContext:ctx]让系统调用此view的drawRect:方法的；因此我们在重写drawLayer:inContext方法的时候需要重写[super drawLayer:layer inContext:ctx]，否则drawRect不执行。
 8.系统在调用drawRect方法之前会调用drawInContext方法。
 9.在一个UIView中添加CALayer的时候，不能将CALayer的代理设置为UIView，当你这样做的时候会发现系统崩溃，原因是UIView和CALayer的代理发生冲突，UIView没有办法绘画自己的CALayer。
 10.在一个UIView中添加CALayer，设置[CALayer setNeedsDisplay]CALayer自身只会调用drawInContext方法。
 
 */
+ (Class)layerClass
{
    NSLog(@"执行LayerClass"); // 该方法发生在initWithFrame之前
    return [CALayer class]; // 这个方法必须返回LayerClass，drawLayer InContext和drawRect才会执行，返回其他类型的不可以。
//    return [CATextLayer class]; // 不执行LayerClass，drawLayer InContext和drawRect
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    NSLog(@"提示：drawLayer InContext");
    
    [super drawLayer:layer inContext:ctx]; // 必须调用父类的drawLayer in context系统才会调用drawRect
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        NSLog(@"initWithFrame");
        self.showString = @"执行InitWithFrame";
        self.layer.backgroundColor = [UIColor redColor].CGColor;
        [self.layer display]; // 这个会造成视图重绘，走的是draw inContext:(CGContextRef)方法，然后调用drawRect方法，一般在自身内部调用
      //  [self.layer setNeedsDisplay]; // 这个只有在视图加载完成的时候才会调用，因此如果在这里执行的话，draw inContext:(CGContextRef)方法是不会走的
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    NSLog(@"提示：drawRect");
    self.showString = @"执行drawRect";
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor redColor] setFill];
    CGContextSaveGState(ctx);
    [[UIColor yellowColor] setFill];
    CGContextAddEllipseInRect(ctx, CGRectMake(100 / 2, 100 / 2, 100, 100));
    CGContextFillPath(ctx);
  //  CGContextFillEllipseInRect(ctx, CGRectMake(100 / 2, 10, 100, 100)); // FillEllipse==AddEllipse+FillPath
    CGContextRestoreGState(ctx);
    CGContextAddEllipseInRect(ctx, CGRectMake(150 / 2, 150 / 2, 50, 50));
  //  CGContextFillEllipseInRect(ctx, CGRectMake(150 / 2, 150, 50, 50));
    CGContextFillPath(ctx);
//    CGContextRef ctx = UIGraphicsGetCurrentContext();
//    CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
//    CGContextSetLineWidth(ctx, 3);
//    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 200, 200));
//    CGContextStrokePath(ctx); // 说明ctx不支持自动剪切不在rect范围之内的内容
}

@end
